﻿
namespace HSS.ComponentModel
{
	#region Using Directives
	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Globalization;
	using HSS.Collections;
	using HSS.Resources;
	#endregion

	#region EnumConverter
	/// <summary>
	/// Provides a type converter to convert Enum objects to and from various other representations.
	/// </summary>
	public class EnumConverter : TypeConverter
	{
		#region Fields
		private Type type;
		#endregion

		#region Constructors
		/// <summary>
		/// Initializes a new instance of the EnumConverter class for the given type.
		/// </summary>
		/// <param name="type">A Type that represents the type of enumeration to associate with this enumeration converter.</param>
		public EnumConverter(Type type)
		{
			this.type = type;
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets an IComparer that can be used to sort the values of the enumeration.
		/// </summary>
		protected virtual IComparer Comparer
		{
			get
			{
				return InvariantComparer.Default;
			}
		}
		/// <summary>
		/// Specifies the type of the enumerator this converter is associated with.
		/// </summary>
		protected Type EnumType
		{
			get
			{
				return this.type;
			}
		}
		#endregion

		#region Overrides
		/// <summary>
		/// Gets a value indicating whether this converter can convert an object in the given source type to an enumeration object using the specified context.
		/// </summary>
		/// <param name="context">An ITypeDescriptorContext that provides a format context.</param>
		/// <param name="sourceType">A Type that represents the type you wish to convert from.</param>
		/// <returns>true if this converter can perform the conversion; otherwise, false.</returns>
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
		{
			if (!(sourceType == typeof(string)) && !(sourceType == typeof(Enum[])))
			{
				return base.CanConvertFrom(context, sourceType);
			}
			return true;
		}
		/// <summary>
		/// Gets a value indicating whether this converter can convert an object to the given destination type using the context.
		/// </summary>
		/// <param name="context">An ITypeDescriptorContext that provides a format context.</param>
		/// <param name="destinationType">A Type that represents the type you wish to convert to.</param>
		/// <returns>true if this converter can perform the conversion; otherwise, false.</returns>
		public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
		{
			if (!(destinationType == typeof(Enum[])))
				return base.CanConvertTo(context, destinationType);
			return true;
		}
		/// <summary>
		/// Converts the specified value object to an enumeration object.
		/// </summary>
		/// <param name="context">An ITypeDescriptorContext that provides a format context.</param>
		/// <param name="culture">An optional CultureInfo. If not supplied, the current culture is assumed.</param>
		/// <param name="value">The Object to convert.</param>
		/// <returns>An Object that represents the converted value.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
		{
			if (value is string)
			{
				try
				{
					string strValue = (string)value;
					if (strValue.IndexOf(',') != -1)
					{
						long num = 0L;
						foreach (string enumStr in strValue.Split(new char[] { ',' }))
						{
							long numVal = Convert.ToInt64((Enum)Enum.Parse(this.type, enumStr, true), culture);
							num |= numVal;
						}
						return Enum.ToObject(this.type, num);
					}
					return Enum.Parse(this.type, strValue, true);
				}
				catch (Exception exception)
				{
					throw new FormatException(ResourceProvider.GetString(StringKeys.InvalidValueForX, new object[] { (string)value, this.type.Name }), exception);
				}
			}
			if (!(value is Enum[]))
			{
				return base.ConvertFrom(context, culture, value);
			}
			long num2 = 0L;
			foreach (Enum enum2 in (Enum[])value)
			{
				num2 |= Convert.ToInt64(enum2, culture);
			}
			return Enum.ToObject(this.type, num2);
		}
		/// <summary>
		/// Converts the given value object to the specified destination type.
		/// </summary>
		/// <param name="context">An ITypeDescriptorContext that provides a format context.</param>
		/// <param name="culture">An optional CultureInfo. If not supplied, the current culture is assumed.</param>
		/// <param name="value">The Object to convert.</param>
		/// <param name="destinationType">The Type to convert the value to.</param>
		/// <returns>An Object that represents the converted value.</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
		{
			if (destinationType == null)
				throw new ArgumentNullException("destinationType");
			if ((destinationType == typeof(string)) && (value != null))
			{
				//Type underlyingType = Enum.GetUnderlyingType(this.type);
				//if ((value is IConvertible) && (value.GetType() != underlyingType))
				//    value = ((IConvertible)value).ToType(underlyingType, culture);
				//if (!this.type.IsDefined(typeof(FlagsAttribute), false) && !Enum.IsDefined(this.type, value))
				//    throw new ArgumentException(string.Format("The value '{0}' is not a valid value for the enum '{1}'.", new object[] { value.ToString(), this.type.Name }));
				string enumStr = ((Enum)value).ToString("G");
				return enumStr;
				//return Enum.Format(this.type, value, "G");
			}
			if (!(destinationType == typeof(Enum[])) || (value == null))
			{
				return base.ConvertTo(context, culture, value, destinationType);
			}
			if (!this.type.IsDefined(typeof(FlagsAttribute), false))
			{
				return new Enum[] { ((Enum)Enum.ToObject(this.type, value)) };
			}
			var list = new List<Enum>();
			var values = EnumHelper.GetValues(this.type);
			var numArray = new long[values.Count];
			for (int i = 0; i < values.Count; i++)
				numArray[i] = Convert.ToInt64((Enum)values[i], culture);
			long num2 = Convert.ToInt64((Enum)value, culture);
			bool flag = true;
			while (flag)
			{
				flag = false;
				foreach (long num3 in numArray)
				{
					if (((num3 != 0L) && ((num3 & num2) == num3)) || (num3 == num2))
					{
						list.Add((Enum)Enum.ToObject(this.type, num3));
						flag = true;
						num2 &= ~num3;
						break;
					}
				}
				if (num2 == 0L)
				{
					break;
				}
			}
			if (!flag && (num2 != 0L))
			{
				list.Add((Enum)Enum.ToObject(this.type, num2));
			}
			return list.ToArray();
		}
		#endregion
	}
	#endregion
}